﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ch.ethz.ssh2.util;

namespace FormsTest
{
    public partial class TerminalDialog : Form
    {
        private LoginMain loginMain;
        internal System.IO.Stream input;
        internal System.IO.Stream output;
        private ch.ethz.ssh2.Session sess;
        private int x_width;
        private int y_width;

        public TerminalDialog()
        {
            InitializeComponent();
        }

        public TerminalDialog(LoginMain loginMain, System.String title, ch.ethz.ssh2.Session sess, int x_width, int y_width)
            : this()
        {
            // TODO: Complete member initialization
            this.loginMain = loginMain;
            this.sess = sess;
            this.x_width = x_width;
            this.y_width = y_width;
        }

        internal char[][] lines;
        internal int posy = 0;
        internal int posx = 0;

        private void addText(byte[] data, int len)
        {
            for (int i = 0; i < len; i++)
            {
                char c = (char)(data[i] & 0xff);

                if (c == 8)
                // Backspace, VERASE
                {
                    if (posx < 0)
                        continue;
                    posx--;
                    continue;
                }

                if (c == '\r')
                {
                    posx = 0;
                    continue;
                }

                if (c == '\n')
                {
                    posy++;
                    if (posy >= y_width)
                    {
                        for (int k = 1; k < y_width; k++)
                            lines[k - 1] = lines[k];
                        posy--;
                        lines[y_width - 1] = new char[x_width];
                        for (int k = 0; k < x_width; k++)
                            lines[y_width - 1][k] = ' ';
                    }
                    continue;
                }

                if (c < 32)
                {
                    continue;
                }

                if (posx >= x_width)
                {
                    posx = 0;
                    posy++;
                    if (posy >= y_width)
                    {
                        posy--;
                        for (int k = 1; k < y_width; k++)
                            lines[k - 1] = lines[k];
                        lines[y_width - 1] = new char[x_width];
                        for (int k = 0; k < x_width; k++)
                            lines[y_width - 1][k] = ' ';
                    }
                }

                if (lines[posy] == null)
                {
                    lines[posy] = new char[x_width];
                    for (int k = 0; k < x_width; k++)
                        lines[posy][k] = ' ';
                }

                lines[posy][posx] = c;
                posx++;
            }

            System.Text.StringBuilder sb = new System.Text.StringBuilder(x_width * y_width);

            for (int i = 0; i < lines.Length; i++)
            {
                if (i != 0)
                    sb.Append('\n');

                if (lines[i] != null)
                {
                    sb.Append(lines[i]);
                }
            }
            terminalArea.Text = sb.ToString();
        }

        public void RemoteConsumer()
        {
            byte[] buff = new byte[8192];

            try
            {
                while (true)
                {
                    int len = (input is ch.ethz.ssh2.StreamGobbler || input is ch.ethz.ssh2.channel.ChannelInputStream) ? (int)Utility.InvokeMethodAsVirtual(input, "read", new System.Object[] { buff }) : Utility.ReadInput(input, buff, 0, buff.Length);
                    if (len == -1)
                        return;
                    addText(buff, len);
                }
            }
            catch (System.Exception e)
            {
            }
        }


        /// <summary>
        /// This method works as a handler for the Control.Layout event, it arranges the controls into the container 
        /// control in a left-to-right orientation.
        /// The location of each control will be calculated according the number of them in the container. 
        /// The corresponding alignment, the horizontal and vertical spacing between the inner controls are specified
        /// as an array of object values in the Tag property of the container.
        /// </summary>
        /// <param name="event_sender">The container control in which the controls will be relocated.</param>
        /// <param name="eventArgs">Data of the event.</param>
        public void FlowLayoutResize(System.Object event_sender, System.Windows.Forms.LayoutEventArgs eventArgs)
        {
            System.Windows.Forms.Control container = (System.Windows.Forms.Control)event_sender;
            if (container.Tag is System.Array)
            {
                System.Object[] items = (System.Object[])container.Tag;
                if (items.Length == 3)
                {
                    container.SuspendLayout();

                    int width = container.Width;
                    int height = container.Height;
                    if (!(container is System.Windows.Forms.ScrollableControl))
                    {
                        width = container.DisplayRectangle.Width;
                        height = container.DisplayRectangle.Height;
                    }
                    else
                        if (container is System.Windows.Forms.Form)
                        {
                            width = ((System.Windows.Forms.Form)container).ClientSize.Width;
                            height = ((System.Windows.Forms.Form)container).ClientSize.Height;
                        }
                    System.Drawing.ContentAlignment alignment = (System.Drawing.ContentAlignment)items[0];
                    int horizontal = (int)items[1];
                    int vertical = (int)items[2];

                    // Split controls in several rows
                    System.Collections.ArrayList rows = new System.Collections.ArrayList();
                    System.Collections.ArrayList list = new System.Collections.ArrayList();
                    int tempWidth = 0;
                    int tempHeight = 0;
                    int totalHeight = 0;
                    for (int index = 0; index < container.Controls.Count; index++)
                    {
                        if (tempHeight < container.Controls[index].Height)
                            tempHeight = container.Controls[index].Height;

                        list.Add(container.Controls[index]);

                        if (index == 0) tempWidth = container.Controls[0].Width;

                        if (index == container.Controls.Count - 1)
                        {
                            rows.Add(list);
                            totalHeight += tempHeight + vertical;
                        }
                        else
                        {
                            tempWidth += horizontal + container.Controls[index + 1].Width;
                            if (tempWidth >= width - horizontal * 2)
                            {
                                rows.Add(list);
                                totalHeight += tempHeight + vertical;
                                tempHeight = 0;
                                list = new System.Collections.ArrayList();
                                tempWidth = container.Controls[index + 1].Width;
                            }
                        }
                    }
                    totalHeight -= vertical;

                    // Break out alignment coordinates
                    int h = 0;
                    int cx = 0;
                    int cy = 0;
                    if (((int)alignment & 0x00F) > 0)
                    {
                        h = (int)alignment;
                        cy = 1;
                    }
                    if (((int)alignment & 0x0F0) > 0)
                    {
                        h = (int)alignment >> 4;
                        cy = 2;
                    }
                    if (((int)alignment & 0xF00) > 0)
                    {
                        h = (int)alignment >> 8;
                        cy = 3;
                    }
                    if (h == 1) cx = 1;
                    if (h == 2) cx = 2;
                    if (h == 4) cx = 3;

                    int ypos = vertical;
                    if (cy == 2) ypos = height / 2 - totalHeight / 2;
                    if (cy == 3) ypos = height - totalHeight - vertical;
                    foreach (System.Collections.ArrayList row in rows)
                    {
                        int maxHeight = PlaceControls(row, width, cx, ypos, horizontal);
                        ypos += vertical + maxHeight;
                    }
                    container.ResumeLayout();
                }
            }
        }

        private int PlaceControls(System.Collections.ArrayList controls, int width, int cx, int ypos, int horizontal)
        {
            int count = controls.Count;
            int controlsWidth = 0;
            int maxHeight = 0;
            foreach (System.Windows.Forms.Control control in controls)
            {
                controlsWidth += control.Width;
                if (maxHeight < control.Height) maxHeight = control.Height;
            }
            controlsWidth += horizontal * (count - 1);

            // Start x point
            int xpos = 0;
            if (cx == 1) xpos = horizontal; // Left
            if (cx == 2) xpos = width / 2 - controlsWidth / 2; // Center
            if (cx == 3) xpos = width - horizontal - controlsWidth; // Right

            // Place controls
            int x = xpos;
            foreach (System.Windows.Forms.Control control in controls)
            {
                int y = ypos + (maxHeight / 2) - control.Height / 2;
                control.Location = new System.Drawing.Point(x, y);
                x += control.Width + horizontal;
            }
            return maxHeight;
        }
    }
}
